<?php
/**
 * CONTENIDO extension pack (mpContenidoX), consists of multiple classes to
 * provide more features for Plugins/Modules.
 *
 * @package     mpContenidoX
 * @subpackage  Bootstrap
 * @author      Murat Purc <murat@purc.de>
 * @copyright   Copyright (c) 2008-2012 Murat Purc (http://www.purc.de)
 * @license     http://www.gnu.org/licenses/gpl-2.0.html - GNU General Public License, version 2
 * @version     $Id: mpAutoload.class.php 21 2012-07-16 21:33:14Z purcaholic $
 */


defined('CON_FRAMEWORK') or die('Illegal call');


/**
 * Autoload class.
 *
 * Implements autoload feature for mp classes in a CONTENIDO project.
 *
 * @package     mpContenidoX
 * @subpackage  Bootstrap
 * @author      Murat Purc <murat@purc.de>
 */
class mpAutoload
{

    const ERROR_FILE_NOT_FOUND = 'file_not_found';

    const ERROR_CLASS_EXISTS = 'class_exists';

    /**
     * Array of interface/class names with related file to include
     *
     * @var array
     */
     private static $_includeFiles = null;

     /**
     * Array to store loaded classnames and the paths to the class files.
     * $_loadedClasses['classname'] = '/path/to/the/class.php';
     *
     * @var array
     */
    private static $_loadedClasses = array();

    /**
     * Array to store invalid classnames and the paths to the class files.
     * $_errors[pos] = array('class' => classname, 'file' => file, 'error' => errorType);
     *
     * @var array
     */
    private static $_errors = array();


    /**
     * The main __autoload() implementation.
     *
     * @param   $className  The classname
     * @return  void
     */
    public static function autoload($className)
    {
        if (isset(self::$_loadedClasses[$className])) {
            return;
        }

        if (strlen($className) > 2 && substr($className, 0, 2) == 'mp') {
            $ord = ord(substr($className, 2, 1));
            if ($ord >= 65 && $ord < 91) {
                // classname begins from mpA* to mpZ*
                if ($file = self::_getClassFile($className)) {
                    self::_loadFile($file);
                }

                self::$_loadedClasses[$className] = str_replace(MP_CLASSES_PATH, '', $file);
            }
        }
    }


    /**
     * Returns the loaded classes (@see mpAutoload::$_loadedClasses)
     *
     * @return  array
     */
    public static function getLoadedClasses()
    {
        return self::$_loadedClasses;
    }


    /**
     * Returns the errorlist containing invalid classes (@see mpAutoload::$_errors)
     *
     * @return  array
     */
    public static function getErrors()
    {
        return self::$_errors;
    }


    /**
     * Returns the path to a mp class file by processing the given classname
     *
     * @return  (string|null)  Path and filename or null
     */
    private static function _getClassFile($className)
    {
        $file = MP_CLASSES_PATH . '/' . str_replace('_', '/', $className) . '.class.php';
        return self::_validateClassAndFile($className, $file);
    }


    /**
     * Validates the given class and the file
     *
     * @param   $className
     * @param   $filePathName
     * @return  (string|null)  The file if validation was successfull, otherwhise null
     */
    private static function _validateClassAndFile($className, $filePathName)
    {
        if (class_exists($className)) {
            self::$_errors[] = array(
                'class' => $className,
                'file'  => str_replace(MP_CLASSES_PATH, '', $filePathName),
                'error' => self::ERROR_CLASS_EXISTS
            );
            return null;
        } elseif (!is_file($filePathName)) {
            self::$_errors[] = array(
                'class' => $className,
                'file'  => str_replace(MP_CLASSES_PATH, '', $filePathName),
                'error' => self::ERROR_FILE_NOT_FOUND
            );
            return null;
        }

        return $filePathName;
    }


    /**
     * Loads the desired file by invoking require_once method
     *
     * @param   $filePathName
     * @return  void
     */
    private static function _loadFile($filePathName)
    {
        require_once($filePathName);
    }

}

